from django.shortcuts import render, redirect, reverse
from django.views import View
from django.http import JsonResponse, HttpResponseForbidden
from .forms import RegisterModelForm, LoginModelForm
from django.contrib.auth import login, authenticate, logout
from apps.user.models import User, Address
from django.contrib.auth.mixins import LoginRequiredMixin
from utils.response_code import RETCODE
from utils.views import LoginRequiredJSONMixin
from celery_tasks.email.tasks import send_email
import json
import re
from .utils import generate_verify_email_url, check_verify_email_token


# 注册
class Register(View):
    def get(self, request):
        return render(request, 'register.html', context={})

    def post(self, request):
        # 1. 校验客户端传递过来的参数 还要校验前端传递过来的短信验证码(暂时没做，后期补上)
        form = RegisterModelForm(request.POST)
        if form.is_valid():
            """
                注册时 短信验证码暂时不验证(短信账户没钱了)
            """
            # # 短信验证码
            # sms_code_client = form.cleaned_data.get('sms_code')
            # mobile = form.cleaned_data.get('mobile')
            # # 判断短信验证码输入是否正确
            # redis_conn = get_redis_connection('verify_code')
            # sms_code_server = redis_conn.get('sms_%s' % mobile)
            #
            # if sms_code_server.decode() is None:
            #     return render(request, 'register.html', {'sms_code_errmsg': '短信验证码已失效'})
            #
            # if sms_code_server.decode() != sms_code_client:
            #     return render(request, 'register.html', {'sms_code_errmsg': '输入短信验证码有误'})
            # 2. 如果表单有效，保存用户并返回成功信息
            user = form.save()
            # 保存数据成功后 注册唯一标识到session和cookie中
            login(request, user)
            return redirect(reverse("contents:index"))
        else:
            # 3. 如果表单无效，返回错误信息
            return JsonResponse({"errors": form.errors}, status=400)


# 根据用户名查询当前用户
class UsernameCountView(View):
    def get(self, request, username):
        count = User.objects.filter(username=username).count()
        return JsonResponse({
            'code': 200,
            'errmsg': 'success',
            'count': count
        })


# 根据手机号查询当前用户
class MobileCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()
        return JsonResponse({
            'code': 200,
            'errmsg': 'success',
            'count': count
        })


# 登录
class LoginView(View):
    def get(self, request):
        return render(request, "login.html")

    # 处理客户端的登录请求
    def post(self, request):
        # 校验参数
        login_form = LoginModelForm(request.POST)
        remember = request.POST.get("remembered")
        if login_form.is_valid():
            # 获取表单校验通过后的数据
            username = login_form.cleaned_data.get('username')
            password = login_form.cleaned_data.get('password')

            # 验证用户名和密码是否正确 utils中重写了authenticate
            user = authenticate(username=username, password=password)
            if user is None:
                # 如果用户名或密码错误，返回错误信息
                return render(request, 'login.html', {'account_errmsg': "账号或密码错误", 'form': login_form})

            # 状态保持：用户登录
            login(request, user)
            # 记住登录状态逻辑
            if remember != True:
                # 没有记住登录，浏览器关闭就销毁
                request.session.set_expiry(0)
            else:
                # 记住登录 状态保持默认两周
                request.session.set_expiry(None)
            # 如果有next字段 就重定向要next指向的路由
            next = request.GET.get('next')
            if next:
                response = redirect(reverse("users:userInfo"))
            else:
                # redirect返回的就是一个response
                response = redirect(reverse("contents:index"))
            # 将用户名保存到cookie中 供前端调用(这种方案比前端调用接口效率更高)
            response.set_cookie("username", user.get_username(), max_age=3600)
            # 登录成功后重定向到首页
            return response

        else:
            # 表单校验失败，返回表单和错误信息
            return render(request, 'login.html&&', {'form': login_form})


# 退出登录
class LogoutView(View):
    def get(self, request):
        logout(request)
        # 退出后进行重定向到首页
        response = redirect(reverse("contents:index"))
        # 清除cookie中的用户信息
        response.delete_cookie("username")
        return response


# 用户中心 通过继承LoginRequiredMixin来实现是否登录的校验
class UserInfoView(LoginRequiredMixin, View):
    def get(self, request):
        context = {
            "username": request.user.username,
            "mobile": request.user.mobile
        }
        return render(request, 'user_center_info.html', context=context)


# 保存邮件 对该方法添加登录验证 返回的是JSON格式 所以需要重写方法
class EmailView(LoginRequiredJSONMixin, View):
    def put(self, request):
        # 获取参数
        email_str = request.body.decode('utf-8')
        email_dict = json.loads(email_str)
        email = email_dict.get('email')
        # 校验参数 正则校验邮箱
        if not re.match('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
            return HttpResponseForbidden("参数格式有误")
        # 存数据
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            JsonResponse({"code": RETCODE.DBERR, 'errmsg': "添加邮箱失败"})
        # 发送邮件（耗时操作 要改为celery 异步）
        verify_url = generate_verify_email_url(request.user)
        send_email.delay(email, verify_url=verify_url)
        # 响应结果
        return JsonResponse({"code": RETCODE.OK, 'errmsg': 'ok'})


# 邮箱激活
class VerifyEmailView(View):
    def get(self, request):
        # 接收token参数
        token = request.GET.get('token')
        if not token:
            return HttpResponseForbidden("缺少token")
        # 解密
        user = check_verify_email_token(token)
        # 激活
        if user.email_active == 0:
            user.email_active = True
        else:
            return HttpResponseForbidden("邮箱已激活")
        return redirect(reverse('users:userInfo'))


# 收货地址
class AddressView(LoginRequiredMixin, View):
    # 获取收货地址列表
    def get(self, request):
        login_user = request.user
        address_set = Address.objects.filter(user=login_user, is_deleted=False)
        address_list = [{
            'id': item.id,
            'receiver': item.title,
            'province': item.province.name,
            'city': item.city.name,
            'district': item.district.name,
            'place': item.place,
            'mobile': item.mobile,
            'tel': item.tel,
            'email': item.email
        } for item in address_set]
        context = {
            'addresses': address_list,
            'default_address_id': login_user.default_address_id,
        }
        print(context)
        return render(request, 'user_center_site.html', context)


# 添加/编辑/删除收货地址
class CreateAndUpdateAddressView(LoginRequiredJSONMixin, View):
    # 添加收货地址
    def post(self, request):
        count = Address.objects.filter(user=request.user).count()
        if count >= 20:
            return JsonResponse({"code": RETCODE.OK, "errmsg": "地址数量超过上限"})
        # 获取传递过来的参数
        params = request.body.decode('utf-8')
        params_dict = json.loads(params)
        receiver = params_dict.get('receiver')
        province_id = params_dict.get('province_id')
        city_id = params_dict.get('city_id')
        district_id = params_dict.get('district_id')
        place = params_dict.get('place')
        mobile = params_dict.get('mobile')
        tel = params_dict.get('tel')
        email = params_dict.get('email')
        # 参数校验 可以使用form也可以这样来校验 根据自己的习惯来选择即可
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return HttpResponseForbidden("缺少必传参数")
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden("手机号格式有误")
        if email and not re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*$', email):
            return HttpResponseForbidden("邮箱格式有误")
        # 保存数据到数据库
        try:
            address = Address.objects.create(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()
        except Exception as e:
            return JsonResponse({"code": RETCODE.DBERR, "errmsg": "新增地址错误"})
        address_dict = {
            'id': address.id,
            'receiver': address.title,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email
        }
        return JsonResponse({"code": RETCODE.OK, "errmsg": "新增地址成功", 'address': address_dict})

    # 更新收货地址
    def put(self, request, address_id):
        # 接收客户端的参数
        params = request.body.decode('utf-8')
        params_dict = json.loads(params)
        print("params_dict---", params_dict)
        receiver = params_dict.get('receiver')
        province_id = params_dict.get('province_id')
        city_id = params_dict.get('city_id')
        district_id = params_dict.get('district_id')
        place = params_dict.get('place')
        mobile = params_dict.get('mobile')
        tel = params_dict.get('tel')
        email = params_dict.get('email')
        # 参数校验 可以使用form也可以这样来校验 根据自己的习惯来选择即可
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return HttpResponseForbidden("缺少必传参数")
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden("手机号格式有误")
        if email and not re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*$', email):
            return HttpResponseForbidden("邮箱格式有误")
        print(request)
        try:
            Address.objects.filter(id=address_id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            return JsonResponse({"code": RETCODE.DBERR, "errmsg": "修改地址失败"})
        address = Address.objects.get(id=address_id)
        address_dict = {
            'id': address.id,
            'receiver': address.title,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email
        }
        return JsonResponse({"code": RETCODE.OK, "errmsg": "修改地址成功", 'address': address_dict})

    # 删除收货地址
    def delete(self, request, address_id):
        # 参数校验
        if not address_id:
            return HttpResponseForbidden("请传入地址id")
        try:
            address = Address.objects.get(id=address_id)
            address.is_deleted = True
            address.save()
        except Exception as e:
            return JsonResponse({"code": RETCODE.DBERR, "errmsg": "删除地址失败"})
        return JsonResponse({"code": RETCODE.OK, "errmsg": "删除地址成功"})


# 设置默认地址
class DefaultAddressView(LoginRequiredJSONMixin, View):
    def put(self, request, address_id):
        # 根据id查询地址
        try:
            address = Address.objects.get(id=address_id)
            request.user.default_address = address
            request.user.save()
        except Exception as e:
            return JsonResponse({"code": RETCODE.DBERR, "errmsg": "设置默认地址失败"})

        return JsonResponse({"code": RETCODE.OK, "errmsg": "设置默认地址成功"})

    pass
